package com.troila.cloud.simplify.web.controller;

import java.io.IOException;
import java.security.MessageDigest;
import java.util.Map;
import java.util.Random;
import java.util.TreeMap;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.troila.cloud.simplify.entity.OpenOrClose;
import com.troila.cloud.simplify.model.WechatMediaAccount;
import com.troila.cloud.simplify.service.WechatMediaAccountService;
import com.troila.cloud.simplify.utils.HttpUtil;

@RestController
@RequestMapping("/")
public class IndexController{
	@Autowired
	private WechatMediaAccountService wechatMediaAccountService;
	/**
	 * 微校提供
	 */
	public static final String API_KEY = "4D4925BCA3A61DB0";
	public static final String API_SECRET = "154F39C0F641205A91DB7F23CE49282F";
	
	@GetMapping("/MP_verify_VBjRxJtsLKJTqmlR.txt")
	public String verify() {
		return "VBjRxJtsLKJTqmlR";
	}
	/**
	 * 公众号基本信息接口
	 */
	public static final String WEIXIAO_MEDIA_INFO = "http://weixiao.qq.com/common/get_media_info";
	
	@RequestMapping(value = "/index", method = { RequestMethod.POST, RequestMethod.GET }) 
	public void welcome(HttpServletRequest request,HttpServletResponse response, Model model) throws Exception {
		System.out.println("type:"+request.getParameter("type"));
		request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");
		switch (request.getParameter("type")) {
		case "open":
			open(request, response);
			break;
		case "close":
			close(request, response);
			break;
		case "config":
			config(request, response);
			break;
		case "monitor":
			monitor(request, response);
			break;
		case "trigger":
			trigger(request, response);
			break;
		case "keyword":
			keyword(request, response);
			break;
		default:
			break;
		}
	}

	/**
	 * 开启应用
	 * 
	 * @return
	 * @throws IOException
	 */
	public void open(HttpServletRequest request, HttpServletResponse response) throws IOException {
		Map<String, String> map = getPostParameter(request);
		String sign = map.get("sign");
		String calSign = calSign(map);
		/** 验证签名 */
		if (calSign.trim().equals(sign.trim())) {
			//获取公众号信息存入数据库
			String mediaId = map.get("media_id");
			System.out.println("open mediaId:"+mediaId);
			WechatMediaAccount wma = new WechatMediaAccount();
			wma.setMediaKey(mediaId);
			wechatMediaAccountService.save(wma,OpenOrClose.open.getValue());
			
			Long localTime = Long.parseLong(String.valueOf(System.currentTimeMillis()).toString().substring(0, 10));
			Long wxTime = Long.parseLong((map.get("timestamp")));
			long timeS = localTime - wxTime;
			/** 检查时间戳 */
			if (timeS >= 0 && timeS < 10) {
				// 对新关键词进行记录和同步用来做消息处理
				/** OK返回正确的json格式数据 */
				response.getWriter().write("{\"errcode\":0,\"errmsg\":\"\",\"is_config\":1}");
			} else {
				response.getWriter().write("{\"errcode\":5003,\"errmsg\":\"请求接口失败\"}");// 可能是重放攻击
			}
		} else {
			response.getWriter().write("{\"errcode\":5004,\"errmsg\":\"签名错误\"}");// 签名错误
		}
	}

	/**
	 * 关闭应用
	 * 
	 * @return
	 */
	public void close(HttpServletRequest request, HttpServletResponse response) throws IOException {
		
		Map<String, String> map = getPostParameter(request);
		String sign = map.remove("sign");
		String calSign = calSign(map);
		/** 验证签名 */
		if (calSign.equals(sign)) {
			String mediaId = map.get("media_id");
			String publicInfo = getMediaInfo(mediaId);
			System.out.println("close info:"+publicInfo);
//			com.alibaba.fastjson.JSONObject pInfo = com.alibaba.fastjson.JSONObject.parseObject(publicInfo);
			WechatMediaAccount wma = new WechatMediaAccount();
			wma.setMediaKey(mediaId);
			wechatMediaAccountService.save(wma,OpenOrClose.close.getValue());
			Long localTime = Long.parseLong(String.valueOf(System.currentTimeMillis()).toString().substring(0, 10));
			Long wxTime = Long.parseLong((map.get("timestamp")));
			long timeS = localTime - wxTime;
			/** 检查时间戳 */
			if (timeS >= 0 && timeS < 10) {
				// 此处做自己想做的操作...
				response.getWriter().write("{\"errcode\":0,\"errmsg\":\"\"}");
			} else {
				response.getWriter().write("{\"errcode\":5003,\"errmsg\":\"请求接口失败\"}");// 可能是重放攻击
			}
		} else {
			response.getWriter().write("{\"errcode\":5004,\"errmsg\":\"签名错误\"}");// 签名错误
		}
	}

	/**
	 * 应用配置页
	 * 
	 * @return
	 * @throws ServletException 
	 */
	public void config(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
		System.out.println("======config begin======");
		Map<String, String> map = new TreeMap<String, String>();
		map.put("media_id", request.getParameter("media_id"));
		map.put("platform", request.getParameter("platform"));
		map.put("timestamp", request.getParameter("timestamp"));
		map.put("nonce_str", request.getParameter("nonce_str"));
		String sign = request.getParameter("sign");
		String calSign = calSign(map);
		/** 验证签名 */
		System.out.println("calSign:"+calSign);
		System.out.println("sign:"+sign);
		if (calSign.equals(sign)) {
			// 将mediaId生成自己的token，将$token放入cookie

			// 跳转应用配置页
//			response.sendRedirect("https://www.weiniekeji.com");
			String mediaInfo = getMediaInfo(request.getParameter("media_id").toString()).toString();
			System.out.println("config info:"+mediaInfo);
			
			String mediaId = map.get("media_id");
			String publicInfo = getMediaInfo(mediaId);
			com.alibaba.fastjson.JSONObject pInfo = com.alibaba.fastjson.JSONObject.parseObject(publicInfo);
			WechatMediaAccount wma = new WechatMediaAccount();
			wma.setAvatarImage(pInfo.getString("avatar_image"));
			wma.setMediaKey(pInfo.getString("media_id"));
			wma.setMediaName(pInfo.getString("name"));
			wma.setMediaType(pInfo.getIntValue("media_type"));
			wma.setMediaUrl(pInfo.getString("media_url"));
			wma.setSchoolCode(pInfo.getString("school_code"));
			wma.setSchoolName(pInfo.getString("school_name"));
			wma.setVerifyType(pInfo.getIntValue("verify_type"));
			wechatMediaAccountService.save(wma,OpenOrClose.open.getValue());
			
			
			// 加载应用的页面
			request.setAttribute("mediaInfo",mediaInfo);
			request.getRequestDispatcher("/back/list").forward(request,response);
//			response.sendRedirect("http://www.mybbtang.com/smallQuestion/index?type=config");
		} else {
			response.getWriter().write("{\"errcode\":5004,\"errmsg\":\"签名错误\"}");// 签名错误
		}
	}

	/**
	 * 应用监控
	 * 
	 * @return
	 */
	public void monitor(HttpServletRequest request, HttpServletResponse response) throws IOException {
		response.getWriter().write(request.getParameter("echostr"));
	}

	/**
	 * 应用触发
	 * 
	 * @return
	 * @throws ServletException 
	 */
	public void trigger(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
		String mediaId = request.getParameter("media_id");
		String mediaInfo = getMediaInfo(mediaId).toString();
		System.out.println("trigger info:"+mediaInfo);
		// 加载应用的页面
		request.setAttribute("mediaInfo",mediaInfo);
		request.getRequestDispatcher("/front/page").forward(request,response);
//		response.sendRedirect("http://www.mybbtang.com/xiaoren/");
	}

	/**
	 * 消息回复类支持模糊匹配的应用需提供此接口
	 */
	public void keyword(HttpServletRequest request, HttpServletResponse response) throws IOException {
		Map<String, String> map = getPostParameter(request);
		String keyword = map.remove("keyword");
		String sign = map.remove("sign");
		String calSign = calSign(map);
		/** 验证签名 */
		if (calSign.equals(sign)) {
			Long localTime = Long.parseLong(String.valueOf(System.currentTimeMillis()).toString().substring(0, 10));
			Long wxTime = Long.parseLong((map.get("timestamp")));
			long timeS = localTime - wxTime;
			/** 检查时间戳 */
			if (timeS >= 0 && timeS < 10) {
				// 此处做自己想做的操作,记录keyword...
				response.getWriter().write("{\"errcode\":0,\"errmsg\":\"\"}");
			} else {
				response.getWriter().write("{\"errcode\":5003,\"errmsg\":\"请求接口失败\"}");// 可能是重放攻击
			}
		} else {
			response.getWriter().write("{\"errcode\":5004,\"errmsg\":\"签名错误\"}");// 签名错误
		}
	}

	/**
	 * 获取POST参数
	 */
	public Map<String, String> getPostParameter(HttpServletRequest request) {
		Map<String, String> requestMap = new TreeMap<String, String>();
		Map<String, String[]> map = request.getParameterMap();
		com.alibaba.fastjson.JSONObject json = null;
		for (String paramterName : map.keySet()) {
			if (paramterName.indexOf("media_id") != -1) {
				json = JSON.parseObject(paramterName);
				requestMap.put("api_key", json.getString("api_key"));
				requestMap.put("media_id", json.getString("media_id"));
				requestMap.put("nonce_str", json.getString("nonce_str"));
				requestMap.put("timestamp", json.getString("timestamp"));
				if (json.getString("keyword") != null) {
					requestMap.put("keyword", json.getString("keyword"));
				}
				requestMap.put("sign", json.getString("sign"));
			}
		}
		return requestMap;
	}

	/**
	 * 计算签名
	 * 
	 * @param map
	 * @return
	 */
	public static String calSign(Map<String, String> map) {
		// 将 mediaId, apiKey, timeStamp, nonceStr四个参数进行字典序排序
		String str = "";
		for (Map.Entry<String, String> entry : map.entrySet()) {
			if(!entry.getKey().equals("sign")) {
				str += entry.getKey() + "=" + entry.getValue() + "&";
			}
		}
		str += "key=" + API_SECRET;
		return md5Encode(str).toUpperCase();
	}

	/**
	 * MD5
	 * 
	 * @param srcString
	 * @return
	 */
	public final static String md5Encode(String srcString) {
		char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
		try {
			byte[] strTemp = srcString.getBytes("UTF-8");
			MessageDigest messageDigest = MessageDigest.getInstance("MD5");
			messageDigest.update(strTemp);
			byte[] mdByte = messageDigest.digest();
			int j = mdByte.length;
			char str[] = new char[j * 2];
			int k = 0;
			for (int i = 0; i < j; i++) {
				byte byte0 = mdByte[i];
				str[k++] = hexDigits[byte0 >>> 4 & 0xf];
				str[k++] = hexDigits[byte0 & 0xf];
			}
			return new String(str);
		} catch (Exception e) {
			return null;
		}
	}
	
	@GetMapping
	public String welcome(HttpServletRequest req, Model model,String mediaId) throws Exception {
		String nonceStr = getRandomString(32);
		String timestamp = String.valueOf(System.currentTimeMillis()).toString().substring(0, 10);
		Map<String, String> map = new TreeMap<String, String>();
		map.put("api_key", API_KEY);
		map.put("media_id", mediaId);
		map.put("timestamp", timestamp);
		map.put("nonce_str", nonceStr);
		map.put("sign", calSign(map));
		return HttpUtil.doPost(WEIXIAO_MEDIA_INFO, JSON.toJSONString(map));
		
	}

	/**
	 * 获取公众号基本信息
	 * 
	 * @return
	 */
	public String getMediaInfo(String mediaId) {
		System.out.println("mediaId:"+mediaId);
		String nonceStr = getRandomString(32);
		String timestamp = String.valueOf(System.currentTimeMillis()).toString().substring(0, 10);
		Map<String, String> map = new TreeMap<String, String>();
		map.put("api_key", API_KEY);
		map.put("media_id", mediaId);
		map.put("timestamp", timestamp);
		map.put("nonce_str", nonceStr);
		map.put("sign", calSign(map));
		return HttpUtil.doPost(WEIXIAO_MEDIA_INFO, JSON.toJSONString(map));
	}

	/**
	 * 生成随机字符串
	 * 
	 * @param length
	 * @return
	 */
	public static String getRandomString(int length) { // length表示生成字符串的长度
		String base = "abcdefghijklmnopqrstuvwxyz0123456789";
		Random random = new Random();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < length; i++) {
			int number = random.nextInt(base.length());
			sb.append(base.charAt(number));
		}
		return sb.toString();
	}
	
}
